#include "ThreadPool.h"
#include <assert.h>


namespace chaos
{
	ThreadPool::ThreadPool(int nThreadNum /*= -1*/) :
		m_threadNum(nThreadNum),
		m_mutex(),
		m_cond(m_mutex),
		m_running(false)
	{
		if (0 >= nThreadNum)
		{
	#ifdef _WIN32
			SYSTEM_INFO systemInfo;
			GetSystemInfo(&systemInfo);
			m_threadNum = systemInfo.dwNumberOfProcessors;
	#else
			m_threadNum = sysconf(_SC_NPROCESSORS_ONLN);
	#endif // _WIN32
		}

		for (uint32 i = 0; i < m_threadNum; ++i)
		{
			m_threads.emplace_back(new Thread(std::bind(&ThreadPool::PoolWorkFunc, this), "thread_pool"));
		}

	}


	ThreadPool::~ThreadPool()
	{
		if (m_running)
		{
			Stop();
		}
	}


	int ThreadPool::Run()
	{
		if (m_running)
			return -1;
		
		m_running = true;

		for (auto& thread : m_threads)
			thread->Start();

		return 0;
	}


	int ThreadPool::Stop()
	{
		{
			LockGuard lock(m_mutex);

			if (!m_running)
				return 0;

			m_running = false;

			m_cond.CondBroadCast();
		}

		for (auto& thread : m_threads)
		{
			thread->Join();
		}

		return 0;
	}


	void ThreadPool::PushTask(const ThreadTask& task)
	{
		if (!task || !m_running)
			return;

		LockGuard lock(m_mutex);

		m_tq.emplace(std::move(task));

		m_cond.CondSignal();
	}


	void ThreadPool::PoolWorkFunc()
	{
		while (m_running)
		{
			ThreadTask task = NULL;
			{
				LockGuard lock(m_mutex);

				while (m_tq.empty() && m_running)
				{
					m_cond.CondWait(/*THREAD_WAIT_TIMEOUT*/);
				}

				//在cond_wait中会因为pool调用stop(置running为false)而跳出循环
				//这里再次判断running状态
				if (!m_running)
					continue;

				//这里m_tq应该一定不为空
				assert(!m_tq.empty());
				task = m_tq.front();

				m_tq.pop();
			}

			if(task)
				task();
		}
	}

}	// namespace chaos

